/*-------------------------------------------------------------------------
This source file is a part of OGRE
(Object-oriented Graphics Rendering Engine)

For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE
-------------------------------------------------------------------------*/
#ifndef __Prerequisites_kernel_H__
#define __Prerequisites_kernel_H__

// Platform-specific stuff
#include "OgrePlatform.h"
#include <string>

// configure memory tracking
#if OGRE_DEBUG_MODE
#   if OGRE_MEMORY_TRACKER_DEBUG_MODE
#       define OGRE_MEMORY_TRACKER 1
#   else
#       define OGRE_MEMORY_TRACKER 0
#   endif
#else
#   if OGRE_MEMORY_TRACKER_RELEASE_MODE
#       define OGRE_MEMORY_TRACKER 1
#   else
#       define OGRE_MEMORY_TRACKER 0
#   endif
#endif

// Define Project Version
#define FD_VERSION_MAJOR 1
#define FD_VERSION_MINOR 1
#define FD_VERSION_PATCH 0

#define FD_VERSION ((FD_VERSION_MAJOR << 16) | (FD_VERSION_MINOR << 8) | FD_VERSION_PATCH)

// Integer formats of fixed bit width
typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef int int32;
typedef short int16;
typedef signed char int8;
/** In order to avoid finger-aches :)
*/
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

typedef char						CHAR;
typedef unsigned char			UCHAR;
typedef wchar_t					WCHAR;
typedef unsigned char			BYTE;
typedef signed char				INT8;
typedef unsigned char			UINT8;
typedef signed short			INT16;
typedef unsigned short		UINT16;
typedef signed int				INT32;
typedef unsigned int			UINT32;

// define uint64 type
#if OGRE_COMPILER == OGRE_COMPILER_MSVC
typedef unsigned __int64 uint64;
typedef __int64 int64;
#else
typedef unsigned long long uint64;
typedef long long int64;
#endif

typedef int64 INT64;
typedef uint64	UINT64;

#if defined(__OS_WIN32__) && _MSC_VER >= 1400
#define _fopen(pFile, filename, mode)    fopen_s(&pFile, filename, mode);
#define _fread(pFile, pDst, nDstSize, nElementSize, nCount)  fread_s(pDst, nDstSize, nElementSize, nCount, pFile);
#define _fwrite(pFile, pBuffer, nElementSize, nCount)  fwrite(pBuffer, nElementSize, nCount, pFile);
#define _strcpy(pDst, nDstSize, pSrc)    strcpy_s(pDst, nDstSize, pSrc);
#else
#define _fopen(pFile, filename, mode)    pFile = fopen(filename, mode);
#define _fread(pFile, pDst, nDstSize, nElementSize, nCount)  fread(pDst, nElementSize, nCount, pFile);
#define _fwrite(pFile, pBuffer, nElementSize, nCount)  fwrite(pBuffer, nElementSize, nCount, pFile);
#define _strcpy(pDst, nDstSize, pSrc)    strcpy(pDst, pSrc);
#endif

// define the real number values to be used
// default to use 'float' unless precompiler option set
#if OGRE_DOUBLE_PRECISION == 1
/** Software floating point type.
@note Not valid as a pointer to GPU buffers / parameters
*/
typedef double Real;
typedef uint64 RealAsUint;
#else
/** Software floating point type.
@note Not valid as a pointer to GPU buffers / parameters
*/
//typedef float Real;
//typedef uint32 RealAsUint;
#endif

namespace FD
{
	namespace Kernel
	{
#ifdef max
#undef max
#endif

#ifdef min
#undef min
#endif

#define FD_PI  3.14159265358979323846
#define FD_PI_2 1.57079632679489661923
#define FD_PI_4 0.78539816339744830962
#define FD_LN_2 0.69314718055994530942
#define FD_INVLN_2 1.0 / LN_2

#define FD_E 2.71828182845904523536
#define FD_LOG2E 1.44269504088896340736
#define FD_LOG10E 0.434294481903251827651
#define FD_LN2 0.693147180559945309417
#define FD_LN10 2.30258509299404568402
#define FD_PI_12 0.2617993877991494365385
#define FD_PI_36 0.0872664526997164788461
#define FD_PI_64 0.04908738521234051935097
#define FD_PI_72 0.04363323129985823942309
#define FD_PI_180 0.017453f
#define FD_1_PI 0.318309886183790671538
#define FD_2_PI 0.636619772367581343076
#define FD_180_PI 57.295779513082323
#define FD_2_SQRTPI         1.12837916709551257390
#define FD_SQRT2            1.41421356237309504880
#define FD_SQRT1_2          0.707106781186547524401

#if OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 310 && !defined(STLPORT)
#   if OGRE_COMP_VER >= 430
#       define OGRE_HashMap ::std::tr1::unordered_map
#       define OGRE_HashMultiMap ::std::tr1::unordered_multimap
#       define OGRE_HashSet ::std::tr1::unordered_set
#       define OGRE_HashMultiSet ::std::tr1::unordered_multiset
#    else
#       define OGRE_HashMap ::__gnu_cxx::hash_map
#       define OGRE_HashMultiMap ::__gnu_cxx::hash_multimap
#       define OGRE_HashSet ::__gnu_cxx::hash_set
#       define OGRE_HashMultiSet ::__gnu_cxx::hash_multiset
#    endif
#elif OGRE_COMPILER == OGRE_COMPILER_CLANG
#    if defined(_LIBCPP_VERSION)
#       define OGRE_HashMap ::std::unordered_map
#       define OGRE_HashMultiMap ::std::unordered_multimap
#       define OGRE_HashSet ::std::unordered_set
#       define OGRE_HashMultiSet ::std::unordered_multiset
#    else
#       define OGRE_HashMap ::std::tr1::unordered_map
#       define OGRE_HashMultiMap ::std::tr1::unordered_multimap
#       define OGRE_HashSet ::std::tr1::unordered_set
#       define OGRE_HashMultiSet ::std::tr1::unordered_multiset
#    endif
#else
#   if OGRE_COMPILER == OGRE_COMPILER_MSVC && !defined(_STLP_MSVC)
#       if _MSC_FULL_VER >= 150030729 // VC++ 9.0 SP1+
#           define OGRE_HashMap ::std::tr1::unordered_map
#           define OGRE_HashMultiMap ::std::tr1::unordered_multimap
#           define OGRE_HashSet ::std::tr1::unordered_set
#           define OGRE_HashMultiSet ::std::tr1::unordered_multiset
#       elif OGRE_THREAD_PROVIDER == 1
#           define OGRE_HashMap ::boost::unordered_map
#           define OGRE_HashMultiMap ::boost::unordered_multimap
#           define OGRE_HashSet ::boost::unordered_set
#           define OGRE_HashMultiSet ::boost::unordered_multiset
#       else
#           define OGRE_HashMap ::std::unordered_map
#           define OGRE_HashMultiMap ::std::unordered_multimap
#           define OGRE_HashSet ::std::unordered_set
#           define OGRE_HashMultiSet ::std::unordered_multiset
#       endif
#   else
#       define OGRE_HashMap ::std::unordered_map
#       define OGRE_HashMultiMap ::std::unordered_multimap
#       define OGRE_HashSet ::std::unordered_set
#       define OGRE_HashMultiSet ::std::unordered_multiset
#   endif
#endif


#define OGRE_DEFINE_STATIC_LOCAL(type, name, arguments) \
	static type& name = *new type arguments

#if __cplusplus >= 201103L
#define register
#endif
		// Pre-declare classes
		// Allows use of pointers in header files without including individual .h
		// so decreases dependencies between files

		class Barrier;
		class DataStream;
		class DefaultWorkQueue;
		class DynLib;
		class DynLibManager;
		class Log;
		class LogManager;
		class MemoryDataStream;
		class Plugin;
		class StringConverter;
		class CStringInterface;
		class Timer;
		class UserObjectBindings;
		class WorkQueue;

		class DataStreamPtr;
		class MemoryDataStreamPtr;
	}
}

/* Include all the standard header *after* all the configuration
settings have been made.
*/
#include "OgreStdHeaders.h"
////#include "OgreMemoryAllocatorConfig.h"
//#include "kernel/OgrePlatform.h"


#if OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR
namespace std
{
#if (OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 430) || OGRE_COMPILER == OGRE_COMPILER_CLANG && !defined(STLPORT) && __cplusplus < 201103L
	namespace tr1
	{
#endif
		template <> struct hash<Ogre::String>
		{
		public :
			size_t operator()(const Ogre::String &str ) const
			{
				size_t _Val = 2166136261U;
				size_t _First = 0;
				size_t _Last = str.size();
				size_t _Stride = 1 + _Last / 10;

				for(; _First < _Last; _First += _Stride)
					_Val = 16777619U * _Val ^ (size_t)str[_First];
				return (_Val);
			}
		};
#if (OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 430) || OGRE_COMPILER == OGRE_COMPILER_CLANG && !defined(STLPORT) && __cplusplus < 201103L
	}
#endif
}
#endif

namespace FD
{
	namespace Kernel
	{
		/** Utility function for constructing an array of objects with placement new,
		without using new[] (which allocates an undocumented amount of extra memory
		and so isn't appropriate for custom allocators).
		*/
		template<typename T>
		T* constructN(T* basePtr, size_t count)
		{
			for (size_t i = 0; i < count; ++i)
			{
				new ((void*)(basePtr+i)) T();
			}
			return basePtr;
		}
		/** @} */
		/** @} */
	}
}



#if OGRE_MEMORY_TRACKER
#define DEBUG_CLIENTBLOCK new(_CLIENT_BLOCK,__FILE__,__LINE__)
#else
#define DEBUG_CLIENTBlOCK new
#endif



#if OGRE_MEMORY_TRACKER

#	define _CRTDBG_MAP_ALLOC
#	include<stdlib.h>
#	ifdef _WIN32
#	include<crtdbg.h>
#	endif

#	define new DEBUG_CLIENTBLOCK

class CrtMemCheck
{
public:

	CrtMemCheck(bool automatic = true)
		: mAutomatic(automatic)
	{
		if (mAutomatic)
		{
			begin();
		}
	}

	~CrtMemCheck()
	{
		if (mAutomatic)
		{
			end();
		}
	}

	inline void setAuto(bool automatic)
	{
		if (mAutomatic != automatic)
		{
			if (mAutomatic)
			{
				end();
			}
			else
			{
				begin();
			}
			mAutomatic = automatic;
		}
	}

	void begin()
	{
		_CrtMemCheckpoint(&s1);
	}

	inline void end()
	{

		_CrtMemCheckpoint(&s2);

		if(_CrtMemDifference(&s3,&s1,&s2))
		{
			_CrtMemDumpStatistics(&s3);
		}

		_CrtDumpMemoryLeaks();

	}

private:

	_CrtMemState s1,s2,s3;

	bool mAutomatic;
};


#endif


#if OGRE_MEMORY_TRACKER

# define PUBLIC_GENERALALLOC

/// Allocate a block of raw memory, and indicate the category of usage
#   define OGRE_MALLOC(bytes) (void *)(new uint8[bytes])
/// Allocate a block of memory for a primitive type, and indicate the category of usage
#   define OGRE_ALLOC_T(T, count) new T[count]
/// Free the memory allocated with OGRE_MALLOC or OGRE_ALLOC_T. Category is required to be restated to ensure the matching policy is used
#   define OGRE_FREE(ptr) delete[] (uint8 *)(ptr)

/// Allocate space for one primitive type, external type or non-virtual type with constructor parameters
#   define OGRE_NEW_T(T) new T
/// Allocate a block of memory for 'count' primitive types - do not use for classes that inherit from AllocatedObject
#   define OGRE_NEW_ARRAY_T(T, count) new T[count]
/// Free the memory allocated with OGRE_NEW_T. Category is required to be restated to ensure the matching policy is used
#   define OGRE_DELETE_T(ptr, T) delete ptr
/// Free the memory allocated with OGRE_NEW_ARRAY_T. Category is required to be restated to ensure the matching policy is used, count and type to call destructor
#   define OGRE_DELETE_ARRAY_T(ptr, T, count) delete[] ptr;


// aligned allocation
/// Allocate a block of raw memory aligned to SIMD boundaries, and indicate the category of usage
#   define OGRE_MALLOC_SIMD(bytes) (void *)(new uint8[bytes])
/// Allocate a block of raw memory aligned to user defined boundaries, and indicate the category of usage
#   define OGRE_MALLOC_ALIGN(bytes, align) (void *)(new uint8[bytes])
/// Allocate a block of memory for a primitive type aligned to SIMD boundaries, and indicate the category of usage
#   define OGRE_ALLOC_T_SIMD(T, count) new T[count]
/// Allocate a block of memory for a primitive type aligned to user defined boundaries, and indicate the category of usage
#   define OGRE_ALLOC_T_ALIGN(T, count, align) new T[count]
/// Free the memory allocated with either OGRE_MALLOC_SIMD or OGRE_ALLOC_T_SIMD. Category is required to be restated to ensure the matching policy is used
#   define OGRE_FREE_SIMD(ptr) delete[] (uint8 *)(ptr)
/// Free the memory allocated with either OGRE_MALLOC_ALIGN or OGRE_ALLOC_T_ALIGN. Category is required to be restated to ensure the matching policy is used
#   define OGRE_FREE_ALIGN(ptr, align) delete[] (uint8 *)(ptr)

/// Allocate space for one primitive type, external type or non-virtual type aligned to SIMD boundaries
#   define OGRE_NEW_T_SIMD(T) new T
/// Allocate a block of memory for 'count' primitive types aligned to SIMD boundaries - do not use for classes that inherit from AllocatedObject
#   define OGRE_NEW_ARRAY_T_SIMD(T, count) new T[count]
/// Free the memory allocated with OGRE_NEW_T_SIMD. Category is required to be restated to ensure the matching policy is used
#   define OGRE_DELETE_T_SIMD(ptr, T) delete ptr
/// Free the memory allocated with OGRE_NEW_ARRAY_T_SIMD. Category is required to be restated to ensure the matching policy is used, count and type to call destructor
#   define OGRE_DELETE_ARRAY_T_SIMD(ptr, T, count) delete[] ptr
/// Allocate space for one primitive type, external type or non-virtual type aligned to user defined boundaries
#   define OGRE_NEW_T_ALIGN(T, align) new T
/// Allocate a block of memory for 'count' primitive types aligned to user defined boundaries - do not use for classes that inherit from AllocatedObject
#   define OGRE_NEW_ARRAY_T_ALIGN(T, count, align) new T[count]
/// Free the memory allocated with OGRE_NEW_T_ALIGN. Category is required to be restated to ensure the matching policy is used
#   define OGRE_DELETE_T_ALIGN(ptr, T, align) delete ptr
/// Free the memory allocated with OGRE_NEW_ARRAY_T_ALIGN. Category is required to be restated to ensure the matching policy is used, count and type to call destructor
#   define OGRE_DELETE_ARRAY_T_ALIGN(ptr, T, count, align) delete[] ptr

// new / delete for classes deriving from AllocatedObject (alignment determined by per-class policy)
// Also hooks up the file/line/function params
// Can only be used with classes that derive from AllocatedObject since customised new/delete needed
#   define OGRE_NEW new
#   define OGRE_DELETE delete

#else

#include "kernel/OgreMemoryAllocatedObject.h"


#if OGRE_MEMORY_ALLOCATOR == OGRE_MEMORY_ALLOCATOR_NEDPOOLING

#  include "OgreMemoryNedPooling.h"
namespace FD
{
	namespace Kernel

	{
		// configure default allocators based on the options above
		// notice how we're not using the memory categories here but still roughing them out
		// in your allocators you might choose to create different policies per category

		// configurable category, for general malloc
		// notice how we ignore the category here, you could specialise
		class CategorisedAllocPolicy : public NedPoolingPolicy{};
		template <size_t align = 0> class CategorisedAlignAllocPolicy : public NedPoolingAlignedPolicy<align>{};
	}
}

#elif OGRE_MEMORY_ALLOCATOR == OGRE_MEMORY_ALLOCATOR_STD

#  include "OgreMemoryStdAlloc.h"
namespace FD
{
	namespace Kernel

	{
		// configure default allocators based on the options above
		// notice how we're not using the memory categories here but still roughing them out
		// in your allocators you might choose to create different policies per category

		// configurable category, for general malloc
		// notice how we ignore the category here
		class CategorisedAllocPolicy : public StdAllocPolicy{};
		template <size_t align = 0> class CategorisedAlignAllocPolicy : public StdAlignedAllocPolicy<align>{};
	}
}

#else
// your allocators here?

#endif

typedef FD::Kernel::AllocatedObject<FD::Kernel::CategorisedAllocPolicy> GeneralAlloc;

# define PUBLIC_GENERALALLOC , public GeneralAlloc

/// Allocate a block of raw memory, and indicate the category of usage
#   define OGRE_MALLOC(bytes) ::FD::Kernel::CategorisedAllocPolicy::allocateBytes(bytes)
/// Allocate a block of memory for a primitive type, and indicate the category of usage
#   define OGRE_ALLOC_T(T, count) static_cast<T*>(::FD::Kernel::CategorisedAllocPolicy::allocateBytes(sizeof(T)*(count)))
/// Free the memory allocated with OGRE_MALLOC or OGRE_ALLOC_T. Category is required to be restated to ensure the matching policy is used
#   define OGRE_FREE(ptr) ::FD::Kernel::CategorisedAllocPolicy::deallocateBytes((void*)ptr)

/// Allocate space for one primitive type, external type or non-virtual type with constructor parameters
#   define OGRE_NEW_T(T) new (::FD::Kernel::CategorisedAllocPolicy::allocateBytes(sizeof(T))) T
/// Allocate a block of memory for 'count' primitive types - do not use for classes that inherit from AllocatedObject
#   define OGRE_NEW_ARRAY_T(T, count) ::FD::Kernel::constructN(::FD::Kernel::CategorisedAllocPolicy::allocateBytes(sizeof(T)*(count))), count)
/// Free the memory allocated with OGRE_NEW_T. Category is required to be restated to ensure the matching policy is used
#   define OGRE_DELETE_T(ptr, T) if(ptr){(ptr)->~T(); ::FD::Kernel::CategorisedAllocPolicy::deallocateBytes((void*)ptr);}
/// Free the memory allocated with OGRE_NEW_ARRAY_T. Category is required to be restated to ensure the matching policy is used, count and type to call destructor
#   define OGRE_DELETE_ARRAY_T(ptr, T, count) if(ptr){for (size_t b = 0; b < count; ++b) { (ptr)[b].~T();} ::FD::Kernel::CategorisedAllocPolicy::deallocateBytes((void*)ptr);}


// aligned allocation
/// Allocate a block of raw memory aligned to SIMD boundaries, and indicate the category of usage
#   define OGRE_MALLOC_SIMD(bytes) FD::Kernel::CategorisedAlignAllocPolicy<0>::allocateBytes(bytes)
/// Allocate a block of raw memory aligned to user defined boundaries, and indicate the category of usage
#   define OGRE_MALLOC_ALIGN(bytes, align) FD::Kernel::CategorisedAlignAllocPolicy<align>::allocateBytes(bytes)
/// Allocate a block of memory for a primitive type aligned to SIMD boundaries, and indicate the category of usage
#   define OGRE_ALLOC_T_SIMD(T, count) static_cast<T*>(FD::Kernel::CategorisedAlignAllocPolicy<0>::allocateBytes(sizeof(T)*(count)))
/// Allocate a block of memory for a primitive type aligned to user defined boundaries, and indicate the category of usage
#   define OGRE_ALLOC_T_ALIGN(T, count, align) static_cast<T*>(FD::Kernel::CategorisedAlignAllocPolicy<align>::allocateBytes(sizeof(T)*(count)))
/// Free the memory allocated with either OGRE_MALLOC_SIMD or OGRE_ALLOC_T_SIMD. Category is required to be restated to ensure the matching policy is used
#   define OGRE_FREE_SIMD(ptr) FD::Kernel::CategorisedAlignAllocPolicy<0>::deallocateBytes(ptr)
/// Free the memory allocated with either OGRE_MALLOC_ALIGN or OGRE_ALLOC_T_ALIGN. Category is required to be restated to ensure the matching policy is used
#   define OGRE_FREE_ALIGN(ptr, align) FD::Kernel::CategorisedAlignAllocPolicy<align>::deallocateBytes(ptr)

/// Allocate space for one primitive type, external type or non-virtual type aligned to SIMD boundaries
#   define OGRE_NEW_T_SIMD(T) new (FD::Kernel::CategorisedAlignAllocPolicy<0>::allocateBytes(sizeof(T))) T
/// Allocate a block of memory for 'count' primitive types aligned to SIMD boundaries - do not use for classes that inherit from AllocatedObject
#   define OGRE_NEW_ARRAY_T_SIMD(T, count) FD::Kernel::constructN(static_cast<T*>(FD::Kernel::CategorisedAlignAllocPolicy<0>::allocateBytes(sizeof(T)*(count))), count)
/// Free the memory allocated with OGRE_NEW_T_SIMD. Category is required to be restated to ensure the matching policy is used
#   define OGRE_DELETE_T_SIMD(ptr, T) if(ptr){(ptr)->~T(); FD::Kernel::CategorisedAlignAllocPolicy<0>::deallocateBytes(ptr);}
/// Free the memory allocated with OGRE_NEW_ARRAY_T_SIMD. Category is required to be restated to ensure the matching policy is used, count and type to call destructor
#   define OGRE_DELETE_ARRAY_T_SIMD(ptr, T, count) if(ptr){for (size_t b = 0; b < count; ++b) { (ptr)[b].~T();} FD::Kernel::CategorisedAlignAllocPolicy<0>::deallocateBytes(ptr);}
/// Allocate space for one primitive type, external type or non-virtual type aligned to user defined boundaries
#   define OGRE_NEW_T_ALIGN(T, align) new (FD::Kernel::CategorisedAlignAllocPolicy<align>::allocateBytes(sizeof(T))) T
/// Allocate a block of memory for 'count' primitive types aligned to user defined boundaries - do not use for classes that inherit from AllocatedObject
#   define OGRE_NEW_ARRAY_T_ALIGN(T, count, align) FD::Kernel::constructN(static_cast<T*>(FD::Kernel::CategorisedAlignAllocPolicy<align>::allocateBytes(sizeof(T)*(count))), count)
/// Free the memory allocated with OGRE_NEW_T_ALIGN. Category is required to be restated to ensure the matching policy is used
#   define OGRE_DELETE_T_ALIGN(ptr, T, align) if(ptr){(ptr)->~T(); FD::Kernel::CategorisedAlignAllocPolicy<align>::deallocateBytes(ptr);}
/// Free the memory allocated with OGRE_NEW_ARRAY_T_ALIGN. Category is required to be restated to ensure the matching policy is used, count and type to call destructor
#   define OGRE_DELETE_ARRAY_T_ALIGN(ptr, T, count, align) if(ptr){for (size_t _b = 0; _b < count; ++_b) { (ptr)[_b].~T();} FD::Kernel::CategorisedAlignAllocPolicy<align>::deallocateBytes(ptr);}

// new / delete for classes deriving from AllocatedObject (alignment determined by per-class policy)
// Also hooks up the file/line/function params
// Can only be used with classes that derive from AllocatedObject since customised new/delete needed
#   define OGRE_NEW new
#   define OGRE_DELETE delete


#endif

//for stl container
namespace FD
{
	namespace Kernel
	{
		//template<class _Ty, class _Ax = std::allocator<_Ty> >
		//class Vector : public FD::Kernel::CReferenced, public std::vector<_Ty, _Ax>
		//{
		//public:
		//	typedef Vector<_Ty> type;
		//	typedef std::vector<_Ty, _Ax> _MyBase;

		//	Vector() : _MyBase()
		//	{ }

		//	explicit Vector(size_type _Count) : _MyBase(_Count)
		//	{ }

		//	Vector(size_type _Count, const _Ty& _Val) : _MyBase()
		//	{ }

		//	template<class _Iter>
		//	Vector(_Iter _First, _Iter _Last) : _MyBase(_First, _Last)
		//	{ }
		//};

		//template<class _Ty, class _Ax = std::allocator<_Ty> >
		//class List : public FD::Kernel::CReferenced, public std::list<_Ty, _Ax>
		//{
		//public:
		//	typedef List<_Ty> type;
		//	typedef std::list<_Ty, _Ax> _MyBase;

		//	List() : _MyBase()
		//	{ };

		//	explicit List(size_type _Count) : _MyBase(_Count)
		//	{ };

		//	List(size_type _Count, const _Ty& _Val) : _MyBase(_Count, _Val)
		//	{ };

		//	template<class _Iter>
		//	List(_Iter _First, _Iter _Last) : _MyBase(_First, _Last)
		//	{ };
		//};

#if defined(__OS_WIN__)
#define RESERVE_CONTAINER_FUNCTION(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	reverse_iterator rbegin()    { return mList.rbegin();}\
	reverse_iterator rend()      { return mList.rend(); }\
	const_reverse_iterator rbegin() const { return mList.rbegin(); }\
	const_reverse_iterator rend() const { return mList.rend(); }\
	iterator erase(iterator pos){ return mList.erase(pos);}\
	iterator erase(iterator first, iterator last){ return mList.erase(first,last);}
#define RESERVE_CONTAINER_FUNCTION_SET(mList) RESERVE_CONTAINER_FUNCTION(mList)
#define RESERVE_CONTAINER_FUNCTION_LIST(mList) RESERVE_CONTAINER_FUNCTION(mList)
#define RESERVE_CONTAINER_FUNCTION_VECTOR(mList) RESERVE_CONTAINER_FUNCTION(mList)
#define RESERVE_CONTAINER_FUNCTION_MAP(mList) RESERVE_CONTAINER_FUNCTION(mList)
#define RESERVE_CONTAINER_FUNCTION_MULTIMAP(mList)\
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	iterator erase(iterator pos){ return mList.erase(pos);}\
	iterator erase(iterator first, iterator last){ return mList.erase(first,last);}
#define RESERVE_CONTAINER_FUNCTION_HASHMAP(mList)  \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	iterator erase(iterator pos){ return mList.erase(pos);}\
	iterator erase(iterator first, iterator last){ return mList.erase(first,last);}
#elif defined(__OS_ANDROID__)
#define RESERVE_CONTAINER_FUNCTION_SET(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	reverse_iterator rbegin()    { return mList.rbegin();}\
	reverse_iterator rend()      { return mList.rend(); }\
	const_reverse_iterator rbegin() const { return mList.rbegin(); }\
	const_reverse_iterator rend() const { return mList.rend(); }\
	void erase(iterator pos){ /*return*/ mList.erase(pos);}\
	void erase(iterator first, iterator last){ /*return*/ mList.erase(first,last);}
#define RESERVE_CONTAINER_FUNCTION_LIST(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	reverse_iterator rbegin()    { return mList.rbegin();}\
	reverse_iterator rend()      { return mList.rend(); }\
	const_reverse_iterator rbegin() const { return mList.rbegin(); }\
	const_reverse_iterator rend() const { return mList.rend(); }\
	iterator erase(iterator pos){ return mList.erase(pos);}\
	iterator erase(iterator first, iterator last){ return mList.erase(first,last);}
#ifdef NEW_HASHMAP
#define RESERVE_CONTAINER_FUNCTION_HASHMAP(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	void erase(iterator pos){ /*return */mList.erase(pos);}\
	void erase(iterator first, iterator last){ /*return*/ mList.erase(first,last);}
#else
#define RESERVE_CONTAINER_FUNCTION_HASHMAP(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	void erase(iterator pos){/* return */mList.erase(pos);}\
	void erase(iterator first, iterator last){ /*return*/ mList.erase(first,last);}
#endif
#define RESERVE_CONTAINER_FUNCTION_VECTOR(mList) RESERVE_CONTAINER_FUNCTION_LIST(mList)
#define RESERVE_CONTAINER_FUNCTION_MAP(mList) RESERVE_CONTAINER_FUNCTION_SET(mList)
#define RESERVE_CONTAINER_FUNCTION_MULTIMAP(mList) RESERVE_CONTAINER_FUNCTION_HASHMAP(mList)
#define RESERVE_CONTAINER_FUNCTION(mList) RESERVE_CONTAINER_FUNCTION_SET(mList)
#elif defined(__OS_LINUX__)
#define RESERVE_CONTAINER_FUNCTION_SET(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	reverse_iterator rbegin()    { return mList.rbegin();}\
	reverse_iterator rend()      { return mList.rend(); }\
	const_reverse_iterator rbegin() const { return mList.rbegin(); }\
	const_reverse_iterator rend() const { return mList.rend(); }\
	void erase(iterator pos){ return mList.erase(pos);}\
	void erase(iterator first, iterator last){ return mList.erase(first,last);}
#define RESERVE_CONTAINER_FUNCTION_LIST(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	reverse_iterator rbegin()    { return mList.rbegin();}\
	reverse_iterator rend()      { return mList.rend(); }\
	const_reverse_iterator rbegin() const { return mList.rbegin(); }\
	const_reverse_iterator rend() const { return mList.rend(); }\
	iterator erase(iterator pos){ return mList.erase(pos);}\
	iterator erase(iterator first, iterator last){ return mList.erase(first,last);}
#ifdef NEW_HASHMAP
#define RESERVE_CONTAINER_FUNCTION_HASHMAP(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	iterator erase(iterator pos){ return mList.erase(pos);}\
	iterator erase(iterator first, iterator last){ return mList.erase(first,last);}
#else
#define RESERVE_CONTAINER_FUNCTION_HASHMAP(mList) \
	iterator begin()    { return mList.begin();}\
	iterator end()      { return mList.end(); }\
	const_iterator begin() const { return mList.begin(); }\
	const_iterator end() const { return mList.end(); }\
	void erase(iterator pos){ return mList.erase(pos);}\
	void erase(iterator first, iterator last){ return mList.erase(first,last);}
#endif
#define RESERVE_CONTAINER_FUNCTION_VECTOR(mList) RESERVE_CONTAINER_FUNCTION_LIST(mList)
#define RESERVE_CONTAINER_FUNCTION_MAP(mList) RESERVE_CONTAINER_FUNCTION_SET(mList)
#define RESERVE_CONTAINER_FUNCTION_MULTIMAP(mList) RESERVE_CONTAINER_FUNCTION_SET(mList)
#define RESERVE_CONTAINER_FUNCTION(mList) RESERVE_CONTAINER_FUNCTION_LIST(mList)
#endif

#define C_DISABLE_COPY(ClassName) \
	ClassName(const ClassName &); \
	ClassName &operator=(const ClassName &);
	}
} // Ogre

#endif // __OgrePrerequisites_H__
